package com.minelx.woods.task.core;

import com.minelx.landisk.filesystem.core.File;
import com.minelx.landisk.filesystem.core.Path;
import com.minelx.landisk.filesystem.core.init.Existence;
import com.minelx.statementsplus.cha.base.ChaSession;
import com.minelx.woods.task.common.Node;
import com.minelx.woods.task.common.csv.Csv;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static java.util.stream.Collectors.toList;

public class SqlTaskValuesHandler {

	private final ChaSession session;

	public SqlTaskValuesHandler(ChaSession session) {
		this.session = session;
	}

	public void handleLeaf(SqlTaskValues leafNode) {
		session.download(leafNode.toTaskCommitment(), leafNode.destination());
	}

	public void handleSub(Node<SqlTaskValues> subNode) {
		mergeTo(subNode.element().destination(), childrenFiles(subNode));
	}

	public static List<File> childrenFiles(Node<SqlTaskValues> subNode) {
		return subNode.children().stream()
				.map(child -> child.element().destination())
				.collect(toList());
	}

	public static void mergeTo(File destination, List<File> tempFiles) {
		List<File> downloadedTempFiles = tempFiles.stream()
				// FIXME 2021/7/27  wait for me!!!    for SingleTask's mistake
				.filter(file -> file.path().exists())
				.collect(toList());

//			PandasHelper.concat(destination, tempFiles);

		try {
			Csv resultCsv = downloadedTempFiles.stream()
					.map(SqlTaskValuesHandler::readFile)
					.map(Csv::text)
					.reduce(Csv::concat)
					.orElseThrow(() -> new RuntimeException("temp files are all non-exists!"));

			destination.write(resultCsv.toText(), StandardCharsets.UTF_8);
//			 cleanup for downloadedTempFiles
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			downloadedTempFiles.stream()
					.map(File::path)
					.map(Path::correspondingExistence)
					.forEach(Existence::remove);
		}
	}

	private static String readFile(File tempFile) {
		try {
			return tempFile.read(StandardCharsets.UTF_8);
		} catch (IOException e) {
			throw new RuntimeException("something is wrong here", e);
		}
	}
}
